DOM模型概述

基本概念

DOM

DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作(比如增删内容)。

浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和 XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。所有的节点和最终的树状结构,都有规范的对外接口。

DOM 只是一个接口规范,可以用各种语言实现。所以严格地说,DOM 不是 JavaScript 语法的一部分,但是 DOM 操作是 JavaScript 最常见的任务,离开了 DOM,JavaScript 就无法控制网页。另一方面,JavaScript 也是最常用于 DOM 操作的语言。

节点

DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM 树),就是由各种不同类型的节点组成。每个节点可以看作是文档树的一片叶子。

节点的类型有七种

浏览器提供一个原生的节点对象Node,上面这七种节点都继承了Node,因此具有一些共同的属性和方法。

节点树

一个文档的所有节点,按照所在的层级,可以抽象成一种树状结构。这种树状结构就是 DOM 树。它有一个顶层节点,下一层都是顶层节点的子节点,然后子节点又有自己的子节点,就这样层层衍生出一个金字塔结构,倒过来就像一棵树。

浏览器原生提供document节点,代表整个文档。

文档的第一层只有一个节点,就是 HTML 网页的第一个标签< html>,它构成了树结构的根节点(root node),其他 HTML 标签节点都是它的下级节点。

除了根节点,其他节点都有三种层级关系。

DOM 提供操作接口,用来获取这三种关系的节点。比如,子节点接口包括firstChild(第一个子节点)和lastChild(最后一个子节点)等属性,同级节点接口包括nextSibling(紧邻在后的那个同级节点)和previousSibling(紧邻在前的那个同级节点)属性。

Node 接口的属性

所有 DOM 节点都继承了 Node 接口,拥有一些共同的属性和方法。这是 DOM 操作的基础。

Node.nodeType

nodeType属性返回一个整数值,表示节点的类型。

Node 对象定义了几个常量,对应这些类型值。

确定节点类型时,使用nodeType属性是常用方法。

Node.nodeName

nodeName属性返回节点的名称。

不同节点的nodeName属性值如下。

Node.nodeValue

nodeValue属性返回一个字符串,表示当前节点本身的文本值,该属性可读写。

只有文本节点(text)和注释节点(comment)有文本值,因此这两类节点的nodeValue可以返回结果,其他类型的节点一律返回null。同样的,也只有这两类节点可以设置nodeValue属性的值,其他类型的节点设置无效。

Node.textContent

textContent属性返回当前节点和它的所有后代节点的文本内容。

textContent属性自动忽略当前节点内部的 HTML 标签,返回所有文本内容。

该属性是可读写的,设置该属性的值,会用一个新的文本节点,替换所有原来的子节点。它还有一个好处,就是自动对 HTML 标签转义。这很适合用于用户提供的内容。

对于文本节点(text)和注释节点(comment),textContent属性的值与nodeValue属性相同。对于其他类型的节点,该属性会将每个子节点的内容连接在一起返回,但是不包括注释节点。如果一个节点没有子节点,则返回空字符串。

文档节点(document)和文档类型节点(doctype)的textContent属性为null。如果要读取整个文档的内容,可以使用document.documentElement.textContent。

Node.baseURI

baseURI属性返回一个字符串,表示当前网页的绝对路径。浏览器根据这个属性,计算网页上的相对路径的 URL。该属性为只读。

如果无法读到网页的 URL,baseURI属性返回null。

该属性的值一般由当前网址的 URL(即window.location属性)决定,但是可以使用 HTML 的< base>标签,改变该属性的值。

设置了以后,baseURI属性就返回标签设置的值。

Node.ownerDocument

Node.ownerDocument属性返回当前节点所在的顶层文档对象,即document对象。

document对象本身的ownerDocument属性,返回null。

Node.nextSibling

Node.nextSibling属性返回紧跟在当前节点后面的第一个同级节点。如果当前节点后面没有同级节点,则返回null。

注意,该属性还包括文本节点和注释节点()。因此如果当前节点后面有空格,该属性会返回一个文本节点,内容为空格。

nextSibling属性可以用来遍历所有子节点。

Node.previousSibling

previousSibling属性返回当前节点前面的、距离最近的一个同级节点。如果当前节点前面没有同级节点,则返回null。

注意,该属性还包括文本节点和注释节点。因此如果当前节点前面有空格,该属性会返回一个文本节点,内容为空格。

Node.parentNode

parentNode属性返回当前节点的父节点。对于一个节点来说,它的父节点只可能是三种类型:元素节点(element)、文档节点(document)和文档片段节点(documentfragment)。

文档节点(document)和文档片段节点(documentfragment)的父节点都是null。另外,对于那些生成后还没插入 DOM 树的节点,父节点也是null。

Node.parentElement

parentElement属性返回当前节点的父元素节点。如果当前节点没有父节点,或者父节点类型不是元素节点,则返回null。

由于父节点只可能是三种类型:元素节点、文档节点(document)和文档片段节点(documentfragment)。parentElement属性相当于把后两种父节点都排除了。

Node.firstChild,Node.lastChild

firstChild属性返回当前节点的第一个子节点,如果当前节点没有子节点,则返回null。

注意,firstChild返回的除了元素节点,还可能是文本节点或注释节点。

lastChild属性返回当前节点的最后一个子节点,如果当前节点没有子节点,则返回null。用法与firstChild属性相同。

Node.childNodes

childNodes属性返回一个类似数组的对象(NodeList集合),成员包括当前节点的所有子节点。

使用该属性,可以遍历某个节点的所有子节点。

文档节点(document)就有两个子节点:文档类型节点(docType)和 HTML 根元素节点。

Node.isConnected

isConnected属性返回一个布尔值,表示当前节点是否在文档之中。

Node 接口的方法

Node.appendChild()

appendChild方法接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点。该方法的返回值就是插入文档的子节点。

如果参数节点是 DOM 已经存在的节点,appendChild方法会将其从原来的位置,移动到新位置。

如果appendChild方法的参数是DocumentFragment节点,那么插入的是DocumentFragment的所有子节点,而不是DocumentFragment节点本身。返回值是一个空的DocumentFragment节点。

Node.hasChildNodes()

hasChildNodes方法返回一个布尔值,表示当前节点是否有子节点。

注意,子节点包括所有节点,哪怕节点只包含一个空格,hasChildNodes方法也会返回true。

判断一个节点有没有子节点,有许多种方法,下面是其中的三种。

Node.cloneNode()

cloneNode方法用于克隆一个节点。它接受一个布尔值作为参数,表示是否同时克隆子节点。它的返回值是一个克隆出来的新节点。

该方法有一些使用注意点。

  1. 克隆一个节点,会拷贝该节点的所有属性,但是会丧失addEventListener方法和on-属性(即node.onclick = fn),添加在这个节点上的事件回调函数。
  2. 该方法返回的节点不在文档之中,即没有任何父节点,必须使用诸如Node.appendChild这样的方法添加到文档之中。
  3. 克隆一个节点之后,DOM 有可能出现两个有相同id属性(即id=”xxx”)的网页元素,这时应该修改其中一个元素的id属性。如果原节点有name属性,可能也需要修改。

Node.insertBefore()

insertBefore方法用于将某个节点插入父节点内部的指定位置。

insertBefore方法接受两个参数,第一个参数是所要插入的节点newNode,第二个参数是父节点parentNode内部的一个子节点referenceNode。newNode将插在referenceNode这个子节点的前面。返回值是插入的新节点newNode。

如果insertBefore方法的第二个参数为null,则新节点将插在当前节点内部的最后位置,即变成最后一个子节点。

注意,如果所要插入的节点是当前 DOM 现有的节点,则该节点将从原有的位置移除,插入新的位置。

由于不存在insertAfter方法,如果新节点要插在父节点的某个子节点后面,可以用insertBefore方法结合nextSibling属性模拟。

如果要插入的节点是DocumentFragment类型,那么插入的将是DocumentFragment的所有子节点,而不是DocumentFragment节点本身。返回值将是一个空的DocumentFragment节点。

Node.removeChild()

removeChild方法接受一个子节点作为参数,用于从当前节点移除该子节点。返回值是移除的子节点。

被移除的节点依然存在于内存之中,但不再是 DOM 的一部分。所以,一个节点移除以后,依然可以使用它,比如插入到另一个节点下面。

如果参数节点不是当前节点的子节点,removeChild方法将报错。

Node.replaceChild()

replaceChild方法用于将一个新的节点,替换当前节点的某一个子节点。

replaceChild方法接受两个参数,第一个参数newChild是用来替换的新节点,第二个参数oldChild是将要替换走的子节点。返回值是替换走的那个节点oldChild。

Node.contains()

contains方法返回一个布尔值,表示参数节点是否满足以下三个条件之一。

Node.compareDocumentPosition()

compareDocumentPosition方法的用法,与contains方法完全一致,返回一个七个比特位的二进制值,表示参数节点与当前节点的关系。

由于compareDocumentPosition返回值的含义,定义在每一个比特位上,所以如果要检查某一种特定的含义,就需要使用比特位运算符。

进行与运算(&)。

Node.isEqualNode(),Node.isSameNode()

isEqualNode方法返回一个布尔值,用于检查两个节点是否相等。所谓相等的节点,指的是两个节点的类型相同、属性相同、子节点相同。

isSameNode方法返回一个布尔值,表示两个节点是否为同一个节点。

Node.normalize()

normailize方法用于清理当前节点内部的所有文本节点(text)。它会去除空的文本节点,并且将毗邻的文本节点合并成一个,也就是说不存在空的文本节点,以及毗邻的文本节点。

该方法是Text.splitText的逆方法。

Node.getRootNode()

getRootNode方法返回当前节点所在文档的根节点。

NodeList 接口

节点都是单个对象,有时需要一种数据结构,能够容纳多个节点。DOM 提供两种节点集合,用于容纳多个节点:NodeList和HTMLCollection。

这两种集合都属于接口规范。许多 DOM 属性和方法,返回的结果是NodeList实例或HTMLCollection实例。

概述

NodeList实例是一个类似数组的对象,它的成员是节点对象。通过以下方法可以得到NodeList实例。

NodeList实例很像数组,可以使用length属性和forEach方法。但是,它不是数组,不能使用pop或push之类数组特有的方法。

注意,NodeList 实例可能是动态集合,也可能是静态集合。所谓动态集合就是一个活的集合,DOM 删除或新增一个相关节点,都会立刻反映在 NodeList 实例。目前,只有Node.childNodes返回的是一个动态集合,其他的 NodeList 都是静态集合。

NodeList.prototype.length

length属性返回 NodeList 实例包含的节点数量。

document.getElementsByTagName返回一个 NodeList 集合。对于那些不存在的 HTML 标签,length属性返回0。

NodeList.prototype.forEach()

forEach方法用于遍历 NodeList 的所有成员。它接受一个回调函数作为参数,每一轮遍历就执行一次这个回调函数,用法与数组实例的forEach方法完全一致。

forEach方法的第二个参数,用于绑定回调函数内部的this,该参数可省略。

NodeList.prototype.item()

item方法接受一个整数值作为参数,表示成员的位置,返回该位置上的成员。

如果参数值大于实际长度,或者索引不合法(比如负数),item方法返回null。如果省略参数,item方法会报错。

所有类似数组的对象,都可以使用方括号运算符取出成员。一般情况下,都是使用方括号运算符,而不使用item方法。

NodeList.prototype.keys(),NodeList.prototype.values(),NodeList.prototype.entries()

这三个方法都返回一个 ES6 的遍历器对象,可以通过for…of循环遍历获取每一个成员的信息。区别在于,keys()返回键名的遍历器,values()返回键值的遍历器,entries()返回的遍历器同时包含键名和键值的信息。

HTMLCollection 接口

概述

HTMLCollection是一个节点对象的集合,只能包含元素节点(element),不能包含其他类型的节点。它的返回值是一个类似数组的对象,但是与NodeList接口不同,HTMLCollection没有forEach方法,只能使用for循环遍历。

HTMLCollection实例都是动态集合,节点的变化会实时反映在集合中。

如果元素节点有id或name属性,那么HTMLCollection实例上面,可以使用id属性或name属性引用该节点元素。如果没有对应的节点,则返回null。

HTMLCollection.prototype.length

length属性返回HTMLCollection实例包含的成员数量。

HTMLCollection.prototype.item()

item方法接受一个整数值作为参数,表示成员的位置,返回该位置上的成员。

如果参数值超出成员数量或者不合法(比如小于0),那么item方法返回null。

HTMLCollection.prototype.namedItem()

namedItem方法的参数是一个字符串,表示id属性或name属性的值,返回对应的元素节点。如果没有对应的节点,则返回null。

ParentNode 接口

节点对象除了继承 Node 接口以外,还会继承其他接口。ParentNode接口表示当前节点是一个父节点,提供一些处理子节点的方法。ChildNode接口表示当前节点是一个子节点,提供一些相关方法。

如果当前节点是父节点,就会继承ParentNode接口。由于只有元素节点(element)、文档节点(document)和文档片段节点(documentFragment)拥有子节点,因此只有这三类节点会继承ParentNode接口。

ParentNode.children

children属性返回一个HTMLCollection实例,成员是当前节点的所有元素子节点。该属性只读。

children属性只包括元素子节点,不包括其他类型的子节点(比如文本子节点)。如果没有元素类型的子节点,返回值HTMLCollection实例的length属性为0。

HTMLCollection是动态集合,会实时反映 DOM 的任何变化。

ParentNode.firstElementChild

firstElementChild属性返回当前节点的第一个元素子节点。如果没有任何元素子节点,则返回null。

ParentNode.lastElementChild

lastElementChild属性返回当前节点的最后一个元素子节点,如果不存在任何元素子节点,则返回null。

ParentNode.childElementCount

childElementCount属性返回一个整数,表示当前节点的所有元素子节点的数目。如果不包含任何元素子节点,则返回0。

ParentNode.append(),ParentNode.prepend()

append方法为当前节点追加一个或多个子节点,位置是最后一个元素子节点的后面。

该方法不仅可以添加元素子节点,还可以添加文本子节点。

注意,该方法没有返回值。

prepend方法为当前节点追加一个或多个子节点,位置是第一个元素子节点的前面。它的用法与append方法完全一致,也是没有返回值。

ChildNode 接口

如果一个节点有父节点,那么该节点就继承了ChildNode接口。

ChildNode.remove()

remove方法用于从父节点移除当前节点。

ChildNode.before(),ChildNode.after()

before方法用于在当前节点的前面,插入一个或多个同级节点。两者拥有相同的父节点。

注意,该方法不仅可以插入元素节点,还可以插入文本节点。

after方法用于在当前节点的后面,插入一个或多个同级节点,两者拥有相同的父节点。用法与before方法完全相同。

ChildNode.replaceWith()

replaceWith方法使用参数节点,替换当前节点。参数可以是元素节点,也可以是文本节点。

document 对象

概述

document对象是文档的根节点,每张网页都有自己的document对象。window.document属性就指向这个对象。只要浏览器开始载入 HTML 文档,该对象就存在了,可以直接使用。

document对象有不同的办法可以获取。

document对象继承了EventTarget接口、Node接口、ParentNode接口。这意味着,这些接口的方法都可以在document对象上调用。除此之外,document对象还有很多自己的属性和方法。

属性

快捷方式属性

以下属性是指向文档内部的某个节点的快捷方式。

document.defaultView

document.defaultView属性返回document对象所属的window对象。如果当前文档不属于window对象,该属性返回null。

document.doctype

对于 HTML 文档来说,document对象一般有两个子节点。第一个子节点是document.doctype,指向< DOCTYPE>节点,即文档类型(Document Type Declaration,简写DTD)节点。HTML 的文档类型节点,一般写成< !DOCTYPE html>。如果网页没有声明 DTD,该属性返回null。

document.firstChild通常就返回这个节点。

document.documentElement

document.documentElement属性返回当前文档的根节点(root)。它通常是document节点的第二个子节点,紧跟在document.doctype节点后面。HTML网页的该属性,一般是节点。

document.body,document.head

document.body属性指向< body>节点,document.head属性指向< head>节点。

这两个属性总是存在的,如果网页源码里面省略了< head>或< body>,浏览器会自动创建。另外,这两个属性是可写的,如果改写它们的值,相当于移除所有子节点。

document.scrollingElement

document.scrollingElement属性返回文档的滚动元素。也就是说,当文档整体滚动时,到底是哪个元素在滚动。

标准模式下,这个属性返回的文档的根元素document.documentElement(即)。兼容(quirk)模式下,返回的是元素,如果该元素不存在,返回null。

document.activeElement

document.activeElement属性返回获得当前焦点(focus)的 DOM 元素。通常,这个属性返回的是< input>、< textarea>、< select>等表单元素,如果当前没有焦点元素,返回< body>元素或null。

document.fullscreenElement

document.fullscreenElement属性返回当前以全屏状态展示的 DOM 元素。如果不是全屏状态,该属性返回null。

节点集合属性

以下属性返回一个HTMLCollection实例,表示文档内部特定元素的集合。这些集合都是动态的,原节点有任何变化,立刻会反映在集合中。

document.links属性返回当前文档所有设定了href属性的< a>及< area>节点。

document.forms

document.forms属性返回所有< form>表单节点。

document.images

document.images属性返回页面所有< img>图片节点。

document.embeds,document.plugins

document.embeds属性和document.plugins属性,都返回所有< embed>节点。

document.scripts

document.scripts属性返回所有< script>节点。

document.styleSheets

document.styleSheets属性返回文档内嵌或引入的样式表集合。

小结

除了document.styleSheets,以上的集合属性返回的都是HTMLCollection实例。

HTMLCollection实例是类似数组的对象,所以这些属性都有length属性,都可以使用方括号运算符引用成员。如果成员有id或name属性,还可以用这两个属性的值,在HTMLCollection实例上引用到这个成员。

文档静态信息属性

以下属性返回文档信息。

document.documentURI,document.URL

document.documentURI属性和document.URL属性都返回一个字符串,表示当前文档的网址。不同之处是它们继承自不同的接口,documentURI继承自Document接口,可用于所有文档;URL继承自HTMLDocument接口,只能用于 HTML 文档。

如果文档的锚点(#anchor)变化,这两个属性都会跟着变化。

document.domain

document.domain属性返回当前文档的域名,不包含协议和接口。

比如,网页的网址是http://www.example.com:80/hello.html, 那么domain属性就等于www.example.com。如果无法获取域名,该属性返回null。

document.domain基本上是一个只读属性,只有一种情况除外。次级域名的网页,可以把document.domain设为对应的上级域名。比如,当前域名是a.sub.example.com,则document.domain属性可以设置为sub.example.com,也可以设为example.com。修改后,document.domain相同的两个网页,可以读取对方的资源,比如设置的 Cookie。

另外,设置document.domain会导致端口被改成null。因此,如果通过设置document.domain来进行通信,双方网页都必须设置这个值,才能保证端口相同

document.location

Location对象是浏览器提供的原生对象,提供 URL 相关的信息和操作方法。通过window.location和document.location属性,可以拿到这个对象。

document.lastModified

document.lastModified属性返回一个字符串,表示当前文档最后修改的时间。不同浏览器的返回值,日期格式是不一样的。

注意,document.lastModified属性的值是字符串,所以不能直接用来比较。Date.parse方法将其转为Date实例,才能比较两个网页。

document.title

document.title属性返回当前文档的标题。默认情况下,返回节点的值。但是该属性是可写的,一旦被修改,就返回修改后的值。

document.characterSet

document.characterSet属性返回当前文档的编码,比如UTF-8、ISO-8859-1等等。

document.referrer

document.referrer属性返回一个字符串,表示当前文档的访问者来自哪里。

document.dir

document.dir返回一个字符串,表示文字方向。它只有两个可能的值:rtl表示文字从右到左,阿拉伯文是这种方式;ltr表示文字从左到右,包括英语和汉语在内的大多数文字采用这种方式。

document.compatMode

compatMode属性返回浏览器处理文档的模式,可能的值为BackCompat(向后兼容模式)和CSS1Compat(严格模式)。

一般来说,如果网页代码的第一行设置了明确的DOCTYPE(比如<!doctype html>),document.compatMode的值都为CSS1Compat。

文档状态属性

document.hidden

document.hidden属性返回一个布尔值,表示当前页面是否可见。如果窗口最小化、浏览器切换了 Tab,都会导致导致页面不可见,使得document.hidden返回true。

document.visibilityState

document.visibilityState返回文档的可见状态。

这个属性可以用在页面加载时,防止加载某些资源;或者页面不可见时,停掉一些页面功能。

document.readyState

document.readyState属性返回当前文档的状态,共有三种可能的值。

这个属性变化的过程如下。

每次状态变化都会触发一个readystatechange事件。

document.cookie属性用来操作浏览器 Cookie。

document.designMode

document.designMode属性控制当前文档是否可编辑,通常用在所见即所得编辑器。该属性只有两个值on和off,默认值为off。

document.implementation

document.implementation属性返回一个DOMImplementation对象。该对象有三个方法,主要用于创建独立于当前文档的新的 Document 对象。

方法

document.open(),document.close()

document.open方法清除当前文档所有内容,使得文档处于可写状态,供document.write方法写入内容。

document.close方法用来关闭document.open()打开的文档。

document.write(),document.writeln()

document.write方法用于向当前文档写入内容。

在网页的首次渲染阶段,只要页面没有关闭写入(即没有执行document.close()),document.write写入的内容就会追加在已有内容的后面。

注意,document.write会当作 HTML 代码解析,不会转义。

如果页面已经解析完成(DOMContentLoaded事件发生之后),再调用write方法,它会先调用open方法,擦除当前文档所有内容,然后再写入。

如果在页面渲染过程中调用write方法,并不会自动调用open方法。(可以理解成,open方法已调用,但close方法还未调用。)

document.write是JavaScript语言标准化之前就存在的方法,现在完全有更符合标准的方法向文档写入内容(比如对innerHTML属性赋值)。所以,除了某些特殊情况,应该尽量避免使用document.write这个方法。

document.writeln方法与write方法完全一致,除了会在输出内容的尾部添加换行符。

注意,writeln方法添加的是 ASCII 码的换行符,渲染成 HTML 网页时不起作用,即在网页上显示不出换行。网页上的换行,必须显式写入

document.querySelector(),document.querySelectorAll()

document.querySelector方法接受一个 CSS 选择器作为参数,返回匹配该选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null。

document.querySelectorAll方法与querySelector用法类似,区别是返回一个NodeList对象,包含所有匹配给定选择器的节点。

这两个方法的参数,可以是逗号分隔的多个 CSS 选择器,返回匹配其中一个选择器的元素节点,这与 CSS 选择器的规则是一致的。

这两个方法都支持复杂的 CSS 选择器。

但是,它们不支持 CSS 伪元素的选择器(比如:first-line和:first-letter)和伪类的选择器(比如:link和:visited),即无法选中伪元素和伪类。

如果querySelectorAll方法的参数是字符串*,则会返回文档中的所有元素节点。另外,querySelectorAll的返回结果不是动态集合,不会实时反映元素节点的变化。

最后,这两个方法除了定义在document对象上,还定义在元素节点上,即在元素节点上也可以调用。

document.getElementsByTagName()

document.getElementsByTagName方法搜索 HTML 标签名,返回符合条件的元素。它的返回值是一个类似数组对象(HTMLCollection实例),可以实时反映 HTML 文档的变化。如果没有任何匹配的元素,就返回一个空集。

HTML 标签名是大小写不敏感的,因此getElementsByTagName方法也是大小写不敏感的。另外,返回结果中,各个成员的顺序就是它们在文档中出现的顺序。

注意,元素节点本身也定义了getElementsByTagName方法,返回该元素的后代元素中符合条件的元素。也就是说,这个方法不仅可以在document对象上调用,也可以在任何元素节点上调用。

document.getElementsByClassName()

document.getElementsByClassName方法返回一个类似数组的对象(HTMLCollection实例),包括了所有class名字符合指定条件的元素,元素的变化实时反映在返回结果中。

由于class是保留字,所以 JavaScript 一律使用className表示 CSS 的class。

参数可以是多个class,它们之间使用空格分隔。

注意,正常模式下,CSS 的class是大小写敏感的。(quirks mode下,大小写不敏感。)

与getElementsByTagName方法一样,getElementsByClassName方法不仅可以在document对象上调用,也可以在任何元素节点上调用。

document.getElementsByName()

document.getElementsByName方法用于选择拥有name属性的 HTML 元素,返回一个类似数组的的对象(NodeList实例),因为name属性相同的元素可能不止一个。

document.getElementById()

document.getElementById方法返回匹配指定id属性的元素节点。如果没有发现匹配的节点,则返回null。

注意,该方法的参数是大小写敏感的。比如,如果某个节点的id属性是main,那么document.getElementById(‘Main’)将返回null。

document.getElementById方法与document.querySelector方法都能获取元素节点,不同之处是document.querySelector方法的参数使用 CSS 选择器语法,document.getElementById方法的参数是元素的id属性。document.getElementById()比document.querySelector()效率高得多。

另外,这个方法只能在document对象上使用,不能在其他元素节点上使用。

document.elementFromPoint(),document.elementsFromPoint()

document.elementFromPoint方法返回位于页面指定位置最上层的元素节点。

elementFromPoint方法的两个参数,依次是相对于当前视口左上角的横坐标和纵坐标,单位是像素。如果位于该位置的 HTML 元素不可返回(比如文本框的滚动条),则返回它的父元素(比如文本框)。如果坐标值无意义(比如负值或超过视口大小),则返回null。

document.elementsFromPoint()返回一个数组,成员是位于指定坐标(相对于视口)的所有元素。

document.caretPositionFromPoint()

document.caretPositionFromPoint()返回一个 CaretPosition 对象,包含了指定坐标点在节点对象内部的位置信息。CaretPosition 对象就是光标插入点的概念,用于确定光标点在文本对象内部的具体位置。

CaretPosition 对象。该对象有两个属性。

document.createElement()

document.createElement方法用来生成元素节点,并返回该节点。

createElement方法的参数为元素的标签名,即元素节点的tagName属性,对于 HTML 网页大小写不敏感,即参数为div或DIV返回的是同一种节点。如果参数里面包含尖括号(即<和>)会报错。

注意,document.createElement的参数可以是自定义的标签名。

document.createTextNode()

document.createTextNode方法用来生成文本节点(Text实例),并返回该节点。它的参数是文本节点的内容。

这个方法可以确保返回的节点,被浏览器当作文本渲染,而不是当作 HTML 代码渲染。因此,可以用来展示用户的输入,避免 XSS 攻击。

document.createAttribute()

document.createAttribute方法生成一个新的属性节点(Attr实例),并返回它。

document.createAttribute方法的参数name,是属性的名称。

document.createComment()

document.createComment方法生成一个新的注释节点,并返回该节点。

document.createComment方法的参数是一个字符串,会成为注释节点的内容。

document.createDocumentFragment()

document.createDocumentFragment方法生成一个空的文档片段对象(DocumentFragment实例)。

DocumentFragment是一个存在于内存的 DOM 片段,不属于当前文档,常常用来生成一段较复杂的 DOM 结构,然后再插入当前文档。这样做的好处在于,因为DocumentFragment不属于当前文档,对它的任何改动,都不会引发网页的重新渲染,比直接修改当前文档的 DOM 有更好的性能表现。

document.createEvent()

document.createEvent方法生成一个事件对象(Event实例),该对象可以被element.dispatchEvent方法使用,触发指定事件。

document.createEvent方法的参数是事件类型,比如UIEvents、MouseEvents、MutationEvents、HTMLEvents。

document.addEventListener(),document.removeEventListener(),document.dispatchEvent()

这三个方法用于处理document节点的事件。它们都继承自EventTarget接口。

document.hasFocus()

document.hasFocus方法返回一个布尔值,表示当前文档之中是否有元素被激活或获得焦点。

注意,有焦点的文档必定被激活(active),反之不成立,激活的文档未必有焦点。比如,用户点击按钮,从当前窗口跳出一个新窗口,该新窗口就是激活的,但是不拥有焦点。

document.adoptNode(),document.importNode()

document.adoptNode方法将某个节点及其子节点,从原来所在的文档或DocumentFragment里面移除,归属当前document对象,返回插入后的新节点。插入的节点对象的ownerDocument属性,会变成当前的document对象,而parentNode属性是null。

注意,document.adoptNode方法只是改变了节点的归属,并没有将这个节点插入新的文档树。所以,还要再用appendChild方法或insertBefore方法,将新节点插入当前文档树。

document.importNode方法则是从原来所在的文档或DocumentFragment里面,拷贝某个节点及其子节点,让它们归属当前document对象。拷贝的节点对象的ownerDocument属性,会变成当前的document对象,而parentNode属性是null。

document.importNode方法的第一个参数是外部节点,第二个参数是一个布尔值,表示对外部节点是深拷贝还是浅拷贝,默认是浅拷贝(false)。虽然第二个参数是可选的,但是建议总是保留这个参数,并设为true。

注意,document.importNode方法只是拷贝外部节点,这时该节点的父节点是null。下一步还必须将这个节点插入当前文档树。

document.createNodeIterator()

document.createNodeIterator方法返回一个子节点遍历器。

document.createNodeIterator方法第一个参数为所要遍历的根节点,第二个参数为所要遍历的节点类型,这里指定为元素节点(NodeFilter.SHOW_ELEMENT)。几种主要的节点类型写法如下。

document.createNodeIterator方法返回一个“遍历器”对象(NodeFilter实例)。该实例的nextNode()方法和previousNode()方法,可以用来遍历所有子节点。

currentNode和previousNode都指向同一个的节点。

注意,遍历器返回的第一个节点,总是根节点。

document.createTreeWalker()

document.createTreeWalker方法返回一个 DOM 的子树遍历器。它与document.createNodeIterator方法基本是类似的,区别在于它返回的是TreeWalker实例,后者返回的是NodeIterator实例。另外,它的第一个节点不是根节点。

document.createTreeWalker方法的第一个参数是所要遍历的根节点,第二个参数指定所要遍历的节点类型(与document.createNodeIterator方法的第二个参数相同)。

document.getSelection()

这个方法指向window.getSelection()。